#include <linux/module.h>
#include <linux/kernel.h>       /**< printk() */
#include <linux/init.h>

#include <linux/slab.h>
#include <linux/types.h>        /**< size_t */
#include <linux/errno.h>        /**< error codes */
#include <linux/string.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>

#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/workqueue.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/pm.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/pinctrl/pinctrl-state.h>

static struct device_node *np = NULL;//设备树节点指针
static unsigned int gpio_num = __INT_MAX__;
struct pinctrl *pinctrl = NULL;
struct pinctrl_state *key_rst0 = NULL;
struct pinctrl_state *key_rst1 = NULL;

static int gpio_probe(struct platform_device *pdev)
{

	struct device *dev = &pdev->dev;
	int ret = 0;
	
	np = pdev->dev.of_node;
	if(np == NULL)
	{
		printk("node is NULL\n");
		return 0;
	}
	//判断DTS是否有gpio信息
	ret = of_property_read_bool(np,"gpios");
	if(ret == false)
	{
		printk("gpios data not exist\n");
		return 0;
	}

	//根据节点获取gpio号
	gpio_num = of_get_named_gpio(np,"gpios",0);
	printk("gpio num = %d",gpio_num);
	//申请GPIO
	ret = gpio_request(gpio_num,"mygpios");
	if(ret)
	{
		printk("gpioo_request error\n");
	}
	printk("request OK!\n");


	//获取GPIO状态
	pinctrl = devm_pinctrl_get(dev);	
	if(IS_ERR(pinctrl))
	{
		dev_info(&pdev->dev,"NO find id pinctrl!\n");
		return -1;
	}
	//获取GPIO的状态
	key_rst0 = pinctrl_lookup_state(pinctrl,"key0_rst0");
	if(IS_ERR(key_rst0))
		dev_info(&pdev->dev,"NO find pinctrl key_rst0!\n");
	else
	{
		pinctrl_select_state(pinctrl,key_rst0);
		printk("Yes find pinctrl key_rst0!\n");
	}
	
	
	mdelay(100);
	//100ms后切换状态
	key_rst1 = pinctrl_lookup_state(pinctrl,"key0_rst1");
	if(IS_ERR(key_rst1))
		dev_info(&pdev->dev,"NO find pinctrl key_rst1!\n");
	else
	{
		pinctrl_select_state(pinctrl,key_rst1);
		printk("Yes find pinctrl key_rst1!\n");
	}
	
	return 0;
	
}

static int gpio_remove(struct platform_device *dev)
{
	gpio_free(gpio_num);
	return 0;
}

static struct of_device_id gpio_of_match[] = {
	{.compatible = "ts,gpio"},
	{	},
};

static struct platform_driver gpio_driver = {
	.driver = {
		.name = "mygpio",
		.of_match_table = of_match_ptr(gpio_of_match),
	},
	.probe = gpio_probe,
	.remove = gpio_remove,

};

static int __init gpio_init(void)
{
	int ret = 0;
	ret = platform_driver_register(&gpio_driver);
	if (ret)
    {
        pr_info("gpio platform_driver_register failed!\n");
        return ret;
    }
    
    pr_info("platform_driver_register OK!\n");

    return ret;
}

static void __exit gpio_exit(void)
{
	
	printk("byebye\n");
}

module_init(gpio_init);
module_exit(gpio_exit);
